package com.guozcc.bootweb.platform.aop;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.guozcc.bootweb.platform.annotation.Trade;
import com.guozcc.bootweb.platform.tools.HttpContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.MDC;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.UUID;

//        多个切面执行顺序
//        com.guozcc.bootweb.platform.aop.TradeAspect: Around before 1 ......
//        com.guozcc.bootweb.platform.aop.TradeAspect: before 1 ......
//        com.guozcc.bootweb.platform.aop.TradeAspect1: Around before 2 ......
//        com.guozcc.bootweb.platform.aop.TradeAspect1: before 2 ......
//        目标方法日志。。。。。
//        com.guozcc.bootweb.platform.aop.TradeAspect1: afterReturning 2 ......
//        com.guozcc.bootweb.platform.aop.TradeAspect1: after 2 ......
//        com.guozcc.bootweb.platform.aop.TradeAspect1: Around after 2 ......
//        com.guozcc.bootweb.platform.aop.TradeAspect: afterReturning 1 ......
//        com.guozcc.bootweb.platform.aop.TradeAspect: after 1 ......
//        com.guozcc.bootweb.platform.aop.TradeAspect: Around after 1 ......

@Slf4j
@Component
@Aspect//定义通知、切点关系
@Order(value = 1)//多个切面的执行顺序  执行顺序从小到大
public class TradeAspect{


    @Pointcut("@annotation(com.guozcc.bootweb.platform.annotation.Trade)")
    public void tradeAspectPointcut(){}


    @Around("tradeAspectPointcut()")
    public Object trade(ProceedingJoinPoint joinPoint) throws Throwable {
        /**
         * 设置日志追踪索引
         */
        MDC.put("traceId", UUID.randomUUID().toString().replace("-",""));


        /**
         * 获取HttpServletRequest
         */
        HttpServletRequest httpServletRequest = HttpContextUtils.getHttpServletRequest();
        String requestURI = httpServletRequest.getRequestURI();
        log.info("请求路径{}",requestURI);

        /**
         * 获取类、方法以及注解相关信息
         */
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        Method method = signature.getMethod();
        Trade autoAnnotation = method.getAnnotation(Trade.class);
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        log.info("请求接口编码tradeCode="+autoAnnotation.tradeCode());
        log.info("请求接口名称tradeName="+autoAnnotation.tradeName());

        /**
         * 获取方法入参信息
         */
        Object[] args = joinPoint.getArgs();
        log.info("接口上送报文【{}】", JSON.toJSONString(args));

        /**
         * 执行目标方法
         */
        Object result = null;
        try{
            result = joinPoint.proceed(args);
        }catch (Exception e){
            log.error("",e);
            result =new JSONObject(){{
                put("ec","99999");
                put("em","执行异常");
            }};
        }
        log.info("接口返回报文【{}】", JSON.toJSONString(result));
        return result;
    }

//    @Before("tradeAspectPointcut()")
//    public void before() {
//        log.info("before 1 ......");
//    }
//
//    @After("tradeAspectPointcut()")
//    public void after() {
//        log.info("after 1 ......");
//    }
//
//    @AfterThrowing("tradeAspectPointcut()")
//    public void afterThrowing() {
//        log.info("afterThrowing 1 ......");
//    }
//
//    @AfterReturning("tradeAspectPointcut()")
//    public void afterReturning() {
//        log.info("afterReturning 1 ......");
//    }

}
